#include <game/gameserver.h>

#include <game/networkplayer.h>
#include <game/localplayer.h>

#include <QHostAddress>
#include <QNetworkInterface>
#include <QDomDocument>
#include <QByteArray>

GameServer::GameServer(KeyManager *manager, QObject *parent) : Game(manager, parent) {
    mySocket = new QUdpSocket(this);
    QHostAddress address;

    //QStringList items;

    foreach(QNetworkInterface interface, QNetworkInterface::allInterfaces()) {
        if (interface.flags().testFlag(QNetworkInterface::IsRunning)) {
            foreach (QNetworkAddressEntry entry, interface.addressEntries()) {
                if (interface.hardwareAddress() != "00:00:00:00:00:00" && entry.ip().toString().contains("."))
                    //items << interface.name() + entry.ip().toString();
                    address = entry.ip();
            }
        }
    }
    //QHostAddress::
    qDebug("%s", address.toString().toStdString().c_str());
    for (int i = 10000; i < 10100; ++i) {
        if (mySocket->bind(address, i)) {
            qDebug("%d", i);
            break;
        }
    }
    connect(mySocket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));

    foreach(Player *pl, myPlayers) {
        if(pl->getType() == "NetworkPlayer") {
            NetworkPlayer *npl = (NetworkPlayer *)pl;
            npl->setSocket(mySocket);
            connect(mySocket, SIGNAL(readyRead()), npl, SLOT(readPendingDatagramms()));
        }
    }
}

void GameServer::timerEvent(QTimerEvent *e) {
    Game::timerEvent(e);

//    QDomDocument doc("XML");
//    QDomElement root = doc.createElement("root");
//    serialize(&doc, &root);
//    doc.appendChild(root);

//    QString xml = doc.toString();

//    QByteArray array(xml.toAscii());
//    array = qCompress(array);
//    QPair<QHostAddress, int> subscriber;
//    foreach(subscriber, mySubscribers) {
//        mySocket->writeDatagram(array, array.size(), subscriber.first, subscriber.second);
//    }
}

void GameServer::play() {
    Game::play();
    QPair<QHostAddress, int> subscriber;
    QByteArray array;
    array.append(QString("<Command>\n  <ChangeState>%1</ChangeState>\n</Command>").arg(getState()));
    array = qCompress(array);
    foreach(subscriber, mySubscribers) {
        mySocket->writeDatagram(array, array.size(), subscriber.first, subscriber.second);
    }
}

void GameServer::pause() {
    Game::pause();
    QPair<QHostAddress, int> subscriber;
    QByteArray array;
    array.append(QString("<Command>\n  <ChangeState>%1</ChangeState>\n</Command>").arg(getState()));
    array = qCompress(array);
    foreach(subscriber, mySubscribers) {
        mySocket->writeDatagram(array, array.size(), subscriber.first, subscriber.second);
    }
}

void GameServer::readPendingDatagrams() {
    while (mySocket->hasPendingDatagrams()) {
        QByteArray array;
        array.resize(mySocket->pendingDatagramSize());
        QHostAddress sender;
        quint16 port;

        mySocket->readDatagram(array.data(), array.size(), &sender, &port);

        array = qUncompress(array);

        QString message = array;
        if (message == "subscribe") {
            mySubscribers.append(QPair<QHostAddress, int>(sender, port));

            QDomDocument doc("XML");
            QDomElement root = doc.createElement("root");
            serialize(&doc, &root);
            doc.appendChild(root);

            QString xml = doc.toString();

            array = QByteArray(xml.toAscii());
            array = qCompress(array);
            mySocket->writeDatagram(array, array.size(), sender, port);

            foreach (Player *pl, myPlayers) {
                if (pl->getType() == "LocalPlayer") {
                    LocalPlayer *lpl = (LocalPlayer *)pl;
                    lpl->setSocket(mySocket, sender, port);
                }
            }
        } else {
            QDomDocument doc("XML");
            doc.setContent(message);
            QDomNode root = doc.firstChild();
            deserializeCommand(root);
        }
    }
}
